package czy.demo.controller;

import czy.demo.pojo.Person;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.script.Script;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.ResultsExtractor;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.UpdateQuery;
import org.springframework.web.bind.annotation.*;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

/* 使用ElasticsearchTemplate的控制器 */
@RestController
@RequestMapping("/template")
public class ElasticsearchTemplateController {

    private static final Logger logger = LoggerFactory.getLogger(ElasticsearchTemplateController.class);

    @Value("${elasticsearch.index-name}")
    private String indexName;

    @Value("${elasticsearch.type}")
    private String type;

    /* ElasticsearchTemplate，可以将es数据直接转化为对象 */
    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    /**
     * 使用指定查询语句进行数据查询，查询为模糊查询，会在实体的所有字段中查询，只要有一个字段包含查询语句，就会返回其内容
     * @param query：查询语句字符串
     * @return：结果对象列表
     */
    @GetMapping("/search/{query}")
    public List<Person> query(@PathVariable String query){
        QueryBuilder builder = QueryBuilders.queryStringQuery(query).field("name");
        NativeSearchQuery searchQuery = new NativeSearchQuery(builder);
        return this.elasticsearchTemplate.queryForList(searchQuery,Person.class);
    }

    /**
     * 高亮查询，普通返回Page和SearchHit都不能得到高亮内容，只有调用toString才能获取高亮内容
     * @return
     */
    @GetMapping("/search/highlight")
    public String queryHighLight(){
        /* 默认只有查询的内容会被高亮显示，但是中文是每个汉字会被包含一次，可能是分词问题 */
        QueryBuilder builder = QueryBuilders.queryStringQuery("天天");
        HighlightBuilder highlightBuilder = new HighlightBuilder().preTags("<hehe>").postTags("</hehe>");
        HighlightBuilder.Field field = new HighlightBuilder.Field("name");
        HighlightBuilder.Field desc = new HighlightBuilder.Field("description");
        NativeSearchQuery searchQuery = new NativeSearchQuery(builder,null,null,highlightBuilder,new HighlightBuilder.Field[]{field,desc});
        return this.elasticsearchTemplate.query(searchQuery, new ResultsExtractor<String>() {
            @Override
            public String extract(SearchResponse response) {
                return Arrays.toString(response.getHits().getHits());
            }
        });
    }

    /**
     * 返回指定索引是否存在
     */
    @GetMapping("/index/exist/{indexName}")
    public boolean indexExist(@PathVariable String indexName){
        return this.elasticsearchTemplate.indexExists(indexName);
    }

    /**
     * 创建索引方法
     */
    @PostMapping("/index/create/{indexName}")
    public boolean createIndex(@PathVariable String indexName){
        return this.elasticsearchTemplate.createIndex(indexName);
    }

    /**
     * 删除索引方法
     */
    @DeleteMapping("index/delete/{indexName}")
    public boolean deleteIndex(@PathVariable String indexName){
        return this.elasticsearchTemplate.deleteIndex(indexName);
    }

    /**
     * 获取指定索引下指定类型映射
     */
    @GetMapping("/mapping/{indexName}/{type}")
    public Map getMapping(@PathVariable String indexName,@PathVariable String type){
        return this.elasticsearchTemplate.getMapping(indexName,type);
    }

    /**
     * 创建一条文档数据
     * @param person：文档数据对象
     * @return：
     */
    @PostMapping("/person/create")
    public Person create(@RequestBody Person person){
        IndexQuery indexQuery = new IndexQuery();
        indexQuery.setId(person.getId());
        indexQuery.setIndexName(this.indexName);
        indexQuery.setType(this.type);
        indexQuery.setObject(person);
        this.elasticsearchTemplate.index(indexQuery);
        return person;
    }

    /**
     * 这个更新操作没有成功,目前仍然使用插入方式进行更新
     */
    @PutMapping("/person/update")
    public Map<String, Object> update(@RequestBody Map<String,Object> person){
        Script script = new Script(Script.DEFAULT_SCRIPT_TYPE,Script.DEFAULT_SCRIPT_LANG,(String) person.get("id"),person);
        UpdateRequest updateRequest = new UpdateRequest();
        updateRequest.script(script);
        UpdateQuery updateQuery = new UpdateQuery();
        updateQuery.setId((String)person.get("id"));
        updateQuery.setIndexName(this.indexName);
        updateQuery.setType(this.type);
        updateQuery.setUpdateRequest(updateRequest);
        this.elasticsearchTemplate.update(updateQuery);
        return person;
    }

    /**
     * 删除文档数据，根据文档id
     * @param id：文档id
     * @return：
     */
    @DeleteMapping("/person/{id}")
    public String delete(@PathVariable String id){
        return this.elasticsearchTemplate.delete(Person.class,id);
    }



}
